package org.pb.user.service.impl;

import org.pb.basic.constant.Constant;
import org.pb.basic.service.impl.BaseServiceImpl;
import org.pb.basic.utils.SmsUtil;
import org.pb.basic.utils.StrUtils;
import org.pb.user.domain.User;
import org.pb.user.mapper.UserMapper;
import org.pb.user.service.IVerifyCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Console;
import java.util.concurrent.TimeUnit;

/**
 * 验证码业务层接口实现类
 * @author pb
 */
@Service
public class VerifyCodeServiceImpl extends BaseServiceImpl implements IVerifyCodeService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate redisTemplate;

    @Override
    public void sendVerifyCode(String phone) {
       getVerifyCode(phone, Constant.REGISTER_CODE_PREFIX);
    }

    @Override
    public void sendBinderVerifyCode(String phone) {
        getVerifyCode(phone, Constant.BINDER_CODE_PREFIX);
    }

    /**
     * 根据电话号码和业务类型，生成对应的验证码
     * @param phone 要发送验证码的手机号码
     * @param type 生成的验证码的业务类型
     */
    public void getVerifyCode(String phone, String type) {
        if (phone == null) {
            // 如果获取到的手机号为空，则抛出异常：请正确填写手机号
            throw new RuntimeException("请正确填写手机号");
        }
        // 根据手机号查询用户信息
        User user = userMapper.getByPhone(phone);
        // 如果当前验证码业务不是绑定业务，且获取到的用户不为空，则表示已经有改手机号注册的用户，抛出异常——该手机号已经注册
        if (type != Constant.BINDER_CODE_PREFIX && user != null) {
            throw new RuntimeException("该手机号已经注册，请直接登陆");
        }
        // 如果手机号存在，则需要通过拼接业务关键字和手机号，来获取对应的验证码
        String verifyPhone  = type + phone;
        Object verifyCode = redisTemplate.opsForValue().get(type + phone);
        System.out.println(verifyCode);
        // 声明字符串变量code为验证码
        String code = null;
        // 声明长整型变量timestamp为时间戳
        Long timestamp = null;
        // 判断根据verifyPhone获取到的value值是为空
        if (verifyCode != null) {
            // 如果verifyCode不为空，则表示不是第一次申请验证码，通过 : 对于获取到的verifyCode进行分隔
            String[] verifies = verifyCode.toString().split(":");
            // 数组的第一个参数为验证码
            code = verifies[0];
            // 数组的第二个参数为时间戳
            timestamp = Long.parseLong(verifies[1]);
            // 当前的时间戳长度差小于一分钟的话，就表示用户在一分钟内重复发送验证码，抛出异常
            if ( System.currentTimeMillis() - timestamp < 1L * 60L * 1000L) {
                throw new RuntimeException("系统错误，不能在一分钟重复申请验证码");
            }
        } else {
            // 如果没有申请过验证码、验证码过期,获取到一个四位的随机验证码
            code = StrUtils.getRandomString(4);
        }
        // 将当前的code和当前时间戳拼接为一个新的验证码字符串
        String newCode = code + ":" + String.valueOf(System.currentTimeMillis());
        // 将其保存到redis中，并设置有效时间为三分钟
        redisTemplate.opsForValue().set(type + phone, newCode, 3L, TimeUnit.MINUTES);
        System.out.println(code);
        // 发送短信
//        SmsUtil.sendMsg(phone, "你当前的验证码为【" + code + "】。有效时间为3分钟，请尽快填写。");
    }

}
